package com.peiwan.ranking.service.impl;

import com.peiwan.ranking.dto.OrderDTO;
import com.peiwan.ranking.dto.RankingDTO;
import com.peiwan.ranking.repository.OrderRepository;
import com.peiwan.ranking.service.RankingService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RankingServiceImpl implements RankingService {

    private final OrderRepository orderRepository;

    public RankingServiceImpl(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @Override
    public List<RankingDTO> getCompanionRanking(Integer year, Integer month) {
        // 如果年份和月份为null，使用当前年月
        if (year == null || month == null) {
            LocalDate now = LocalDate.now();
            year = now.getYear();
            month = now.getMonthValue();
        }

        // 获取订单数据
        List<OrderDTO> orders = orderRepository.findByYearAndMonth(year, month);
        
        // 按陪陪分组并计算统计数据
        Map<String, List<OrderDTO>> companionOrders = orders.stream()
                .filter(order -> order.getCompanion() != null && !order.getCompanion().isEmpty())
                .collect(Collectors.groupingBy(OrderDTO::getCompanion));
        
        // 转换为排名DTO并排序
        List<RankingDTO> rankings = companionOrders.entrySet().stream()
                .map(entry -> createRankingDTO(entry.getKey(), entry.getValue(), "companion"))
                .sorted(Comparator.comparing(RankingDTO::getAmount).reversed())
                .collect(Collectors.toList());
        
        // 设置排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        return rankings;
    }

    @Override
    public List<RankingDTO> getDispatchRanking(Integer year, Integer month) {
        // 如果年份和月份为null，使用当前年月
        if (year == null || month == null) {
            LocalDate now = LocalDate.now();
            year = now.getYear();
            month = now.getMonthValue();
        }

        // 获取订单数据
        List<OrderDTO> orders = orderRepository.findByYearAndMonth(year, month);
        
        // 按派单分组并计算统计数据
        Map<String, List<OrderDTO>> dispatchOrders = orders.stream()
                .filter(order -> order.getDispatch() != null && !order.getDispatch().isEmpty())
                .collect(Collectors.groupingBy(OrderDTO::getDispatch));
        
        // 转换为排名DTO并排序
        List<RankingDTO> rankings = dispatchOrders.entrySet().stream()
                .map(entry -> createRankingDTO(entry.getKey(), entry.getValue(), "dispatch"))
                .sorted(Comparator.comparing(RankingDTO::getAmount).reversed())
                .collect(Collectors.toList());
        
        // 设置排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        return rankings;
    }

    @Override
    public List<RankingDTO> getReceptionistRanking(Integer year, Integer month) {
        // 如果年份和月份为null，使用当前年月
        if (year == null || month == null) {
            LocalDate now = LocalDate.now();
            year = now.getYear();
            month = now.getMonthValue();
        }

        // 获取订单数据
        List<OrderDTO> orders = orderRepository.findByYearAndMonth(year, month);
        
        // 按接待分组并计算统计数据
        Map<String, List<OrderDTO>> receptionistOrders = orders.stream()
                .filter(order -> order.getReceptionist() != null && !order.getReceptionist().isEmpty())
                .collect(Collectors.groupingBy(OrderDTO::getReceptionist));
        
        // 转换为排名DTO并排序
        List<RankingDTO> rankings = receptionistOrders.entrySet().stream()
                .map(entry -> createRankingDTO(entry.getKey(), entry.getValue(), "receptionist"))
                .sorted(Comparator.comparing(RankingDTO::getAmount).reversed())
                .collect(Collectors.toList());
        
        // 设置排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        return rankings;
    }
    
    /**
     * 创建排名DTO
     * @param name 名称
     * @param orders 订单列表
     * @param type 类型：companion/dispatch/receptionist
     * @return 排名DTO
     */
    private RankingDTO createRankingDTO(String name, List<OrderDTO> orders, String type) {
        RankingDTO rankingDTO = new RankingDTO();
        rankingDTO.setName(name);
        
        // 计算总流水（所有类型都使用totalPrice）
        BigDecimal totalAmount = orders.stream()
                .map(o -> o.getTotalPrice() != null ? o.getTotalPrice() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        rankingDTO.setAmount(totalAmount);
        
        // 设置订单数量
        rankingDTO.setOrderCount(orders.size());
        
        // 计算总时长
        int totalDuration = orders.stream()
                .mapToInt(o -> o.getDuration() != null ? o.getDuration() : 0)
                .sum();
        rankingDTO.setTotalDuration(totalDuration);
        
        // 计算平均订单金额
        if (orders.size() > 0) {
            rankingDTO.setAverageOrderAmount(totalAmount.divide(BigDecimal.valueOf(orders.size()), 2, RoundingMode.HALF_UP));
        } else {
            rankingDTO.setAverageOrderAmount(BigDecimal.ZERO);
        }
        
        // 计算平均时长
        if (orders.size() > 0) {
            rankingDTO.setAverageDuration((double) totalDuration / orders.size());
        } else {
            rankingDTO.setAverageDuration(0.0);
        }

        // 计算团抽总额
        BigDecimal totalGroupCommission = orders.stream()
                .map(o -> o.getGroupCommission() != null ? o.getGroupCommission() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        rankingDTO.setTotalGroupCommission(totalGroupCommission);
        
        // 设置实际收入（根据不同类型使用不同的佣金）
        BigDecimal actualIncome;
        if ("companion".equals(type)) {
            actualIncome = orders.stream()
                    .map(o -> o.getFinalAmount() != null ? o.getFinalAmount() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        } else if ("dispatch".equals(type)) {
            actualIncome = orders.stream()
                    .map(o -> o.getDispatchCommission() != null ? o.getDispatchCommission() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        } else { // receptionist
            actualIncome = orders.stream()
                    .map(o -> o.getReceptionCommission() != null ? o.getReceptionCommission() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        rankingDTO.setActualIncome(actualIncome);
        
        return rankingDTO;
    }
}